This page last changed on Apr 29, 2014 by carueda.

These are some notes about the servo model design and implementation.

Here are some of the plots generated from the unit tests:

Design in a nutshell

At time of writing the code resides in the 'servomodel' branch:
https://github.com/MBARI-ESP/ESP2Gscript/tree/servomodel

The main source file, where the I2C::Servo::Model class is defined is: servomodel.rb.

The servo simulation is modularized in a layered way. Elements of the modeling itself are under the ServoModeling module:

  • Servo::Model and related elements are only concerned, in terms of the characterization of the velocity-position function, with ServoChannelSimulator.
  • ServoChannelSimulator makes use of a FunctionFactory to keep and adjust the overall velocity-position function according to move commands.
  • FunctionFactory facilitates the construction of Function's.
  • Possible Function's are:
    • ConstantFunction: function always evaluating to [0, pos] for a given position
    • MonotoneFunction: captures the basic velocity profile of starting at a given velocity, and then going through acceleration, plateau (each of which can be of zero duration), and deceleration zones. Starting at a given initial position, this function changes the position monotonically in a given direction.
    • CompositeFunction: function composed of the concatenation of multiple functions, each applied from a specific time wrt the previous one.

Testing

Unit tests

All unit tests can be run at the command line as follows:

$ find test/lib/i2c/model -name \*_test.rb -exec ruby -I. -Ilib -Iutils -Itest/lib {} \;
Loaded suite test/lib/i2c/model/servo/function_test
Started
..........
Finished in 0.013645 seconds.

10 tests, 607 assertions, 0 failures, 0 errors
Loaded suite test/lib/i2c/model/servo/functionfact_test
Started
..........
Finished in 0.029115 seconds.

10 tests, 1068 assertions, 0 failures, 0 errors
Loaded suite test/lib/i2c/model/servo/servochannelsim_test
Started
.......
Finished in 0.08877 seconds.

7 tests, 2531 assertions, 0 failures, 0 errors
Loaded suite test/lib/i2c/model/servomodel_test
Started
.......
Finished in 0.188708 seconds.

7 tests, 184 assertions, 0 failures, 0 errors

Test with actual integration in the framework

The following tested in both simfast and simreal modes:

carueda@bufflehead:~/esp2$ . bin/ESPenv shallow moe
carueda@bufflehead:~/esp2$ ESPmode=simfast
carueda@bufflehead:~/esp2$ esp
ESPmoe:001:0-> require 'plot'
true
ESPmoe:002:0-> ssLog = SS.log {SS.home.empty; SS.fill}
SS.reconfigure SSconfig
SS.home.seek empty
@16:00:00.82 SS.seek 25.00ml
[<I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=-12, velocity=-12, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>,
...
 <I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=108084, velocity=12, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>,
 <I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=108096, velocity=0, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>]
ESPmoe:003:0-> plot ssLog
#<Thread::PLOT_1 priority=1 sleep>
ESPmoe:004:0->

The generated plot:

Some other commands:

@09:23:13.98 -> SS.status
#<struct I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=108096, velocity=0, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>
@09:23:18.32 -> SS.goal

@09:23:25.46 -> SS.getConfig
#<struct I2C::Servo::Configuration samplePeriod=1, encoder=:negative, threshold=:off, home=:negative, jogHome=false, homeDirection=false, thresholdOffset=0, maxPositionErr=1000, stopWindow=6, gain=#<struct PIDgain P=400, I=12000, D=1000>, acceleration=6, deceleration=0, stopRate=0, maxSpeed=150, minSpeed=15, maxPWM=98, minPWM=-98, maxSettling=64, maxCurrent=600, stiction=5, friction=60, hunt=true, brake=true, maxDeltaPress=false, maxInPress=0, maxOutPress=0, minDeltaPress=false, minInPress=0, minOutPress=0, pressBias=0, pressGain=0, inputDeltaPress=false, externalCurrent=false, debug=false>

@09:24:30.19 -> SS.setPosition! 2
SS.setPosition! 2.00ml
Sampler Syringe at 2.00ml
@09:24:35.31 -> SS.status
#<struct I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=5472, velocity=0, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>

@09:25:03.46 -> SS.jog -3000
SS.jog -3000
Sampler Syringe at 1.33ml

@09:25:29.29 -> SS.status
#<struct I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=2472, velocity=0, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>

@09:25:50.72 -> SS.to 5
@09:25:50.73 SS.seek 5.00ml
Sampler Syringe at 5.00ml
@09:25:54.42 -> SS.status
#<struct I2C::Servo::Status enabled=false, pastRLS=false, pastFLS=false, pastThreshold=false, lost=false, home=false, position=18858, velocity=0, current=0, pwm=0, err=0, inPress=0, outPress=0, deltaPress=0, voltage=12.1620363279332>

Document generated by Confluence on Feb 03, 2026 14:16